#include "InPerUartHandle.h"
#include "InSdkCallbackFunction.h"
#include "InSdkSoundPlay.h"
#include "SdkMediaInit.h"
#include "InPerLed.h"

#define DEF_TAG     "Serial"

extern SPerUartReadWaitInfo g_InPer_UartRead_Wait_Info[COMMAND_MAX_NUM];

typedef struct
{
    Com_u32 len;
    EPerUartCmdType cmd;
}SUartCmdAndLen,*pSUartCmdAndLen;

static Com_void InPer_UartRead_Wait_Flag(EPerUartCmdType type)
{
    Com_s32 i = 0;

    while(g_InPer_UartRead_Wait_Info[type].flag == DEF_COM_FALSE)
    {
        if(i >= DEF_PER_UART_READ_MS)
        {
            break;
        }
        usleep(2000 / DEF_PER_UART_READ_MS * 1000);
        i++;
    }
}

Com_pvoid InPer_UartRead_Wait_Thread(Com_pvoid arg)
{
    EPerUartCmdType type = (EPerUartCmdType)arg;

    InPer_UartRead_Wait_Flag(type);

    if(g_InPer_UartRead_Wait_Info[type].flag == DEF_COM_FALSE)
    {
        if(g_InPer_UartRead_Wait_Info[type].cnt <= 3)
        {
            g_InPer_UartRead_Wait_Info[type].again = DEF_COM_TRUE;
            g_InPer_UartRead_Wait_Info[type].cnt++;
        }
    }

    return NULL;
}

Com_void InPer_UartRead_Result(EPerUartCmdType cmd)
{
    pthread_t id;

    pthread_create(&id, NULL,InPer_UartRead_Wait_Thread,(Com_pvoid)cmd);
    pthread_detach(id);
}

Com_s32 InPer_UartSend_Data(pSUartCmdAndLen cmd,Com_pu8 buf)
{
    SPerUartData data;

    memset(&data,0,sizeof(data));

    data.data[0] = DEF_HEAD_FIRST;
    data.data[1] = DEF_HEAD_SECOND;
    data.data[2] = DEF_HEAD_VERSION;
    data.data[3] = cmd->cmd;
    data.data[4] = cmd->len / 0x100;
    data.data[5] = cmd->len % 0x100;

    memcpy(data.data + DEF_HEAD_LENGTH,buf,cmd->len);
    data.length = DEF_HEAD_LENGTH + cmd->len;
    data.data[data.length] = Ext_InPer_Uart_CheckSum(data.data,cmd->len);
    data.length++;

    Ext_InPer_Uart_Write(data.data,data.length);

    return 0;
}

Com_void Ext_InPer_UartSend_ManulFeed(Com_s32 feed_num)
{
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_MANUAL_FEED;
    cmd.len = 0x01;

    data[0] = feed_num;

    g_InPer_UartRead_Wait_Info[cmd.cmd].flag = DEF_COM_FALSE;

    InPer_UartSend_Data(&cmd,data);
    InPer_UartRead_Wait_Flag(cmd.cmd);
    if(g_InPer_UartRead_Wait_Info[cmd.cmd].flag == DEF_COM_FALSE)
    {
        PRT_NORMAL("cmd send again: %02x\n",cmd.cmd);
    }

    return;
}

Com_void Ext_InPer_UartSend_Get_Time(Com_void)
{
    Com_u32 lenght = 0;
    SUartCmdAndLen cmd;
    StComDateWeek date_week;
    Com_u8 data[24];

    memset(data,0,sizeof(data));
    memset(&date_week,0,sizeof(date_week));
    Ext_InComTimer_GetDate(&date_week);

    cmd.cmd = COMMAND_MCU_GET_TIME;
    cmd.len = 0x08;

    /* time flag */
    if(Ext_InComFile_Access(DEF_FLAG_SYNC_TIME_OK) == DEF_COM_FILE_EXIST)
    {
        data[lenght++] = 1;
    }
    else
    {
        data[lenght++] = 0;
    }

    data[lenght++] = date_week.year - 2000;
    data[lenght++] = date_week.mon;
    data[lenght++] = date_week.day;
    data[lenght++] = date_week.hour;
    data[lenght++] = date_week.min;
    data[lenght++] = date_week.sec;
    data[lenght++] = date_week.week;

    PRT_DBG(DEF_TAG, "time %d-%d-%d %d-%d-%d,w %d\n", date_week.year,date_week.mon,
    date_week.day, date_week.hour, date_week.min, date_week.sec,date_week.week);
    g_InPer_UartRead_Wait_Info[COMMAND_SET_MCU_TIME].flag = DEF_COM_FALSE;
    InPer_UartSend_Data(&cmd,data);
    InPer_UartRead_Result(COMMAND_SET_MCU_TIME);
}

Com_void Ext_InPer_UartSend_Set_Time(Com_void)
{
    Com_u32 lenght = 0;
    SUartCmdAndLen cmd;
    StComDateWeek date_week;
    Com_u8 data[24];

    memset(data,0,sizeof(data));
    memset(&date_week,0,sizeof(date_week));
    Ext_InComTimer_GetDate(&date_week);

    cmd.cmd = COMMAND_SET_MCU_TIME;
    cmd.len = 0x08;

    /* time flag */
    if(Ext_InComFile_Access(DEF_FLAG_SYNC_TIME_OK) == DEF_COM_FILE_EXIST)
    {
        data[lenght++] = 1;
    }
    else
    {
        data[lenght++] = 0;
    }

    data[lenght++] = date_week.year - 2000;
    data[lenght++] = date_week.mon;
    data[lenght++] = date_week.day;
    data[lenght++] = date_week.hour;
    data[lenght++] = date_week.min;
    data[lenght++] = date_week.sec;
    data[lenght++] = date_week.week;

    PRT_DBG(DEF_TAG, "time %d-%d-%d %d-%d-%d,w %d\n", date_week.year,date_week.mon,
    date_week.day, date_week.hour, date_week.min, date_week.sec,date_week.week);
    g_InPer_UartRead_Wait_Info[COMMAND_SET_MCU_TIME].flag = DEF_COM_FALSE;
    InPer_UartSend_Data(&cmd,data);
    InPer_UartRead_Result(COMMAND_SET_MCU_TIME);
}

Com_void Ext_InPer_UartHandle_Remind(Com_pu8 buf)
{
}

Com_void Ext_InPer_UartHandle_Feed_Result(Com_pu8 buf)
{
}

Com_void Ext_InPer_UartSend_Version(Com_void)
{
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_CHECK_VERSION;
    cmd.len = 0x00;

    g_InPer_UartRead_Wait_Info[cmd.cmd].flag = DEF_COM_FALSE;
    InPer_UartSend_Data(&cmd,data);
    InPer_UartRead_Result(cmd.cmd);
}

Com_void Ext_InPer_UartSend_Reset(Com_void)
{
#if 0
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_DEVIVE_RESET;
    cmd.len = 0x00;

    g_InPer_UartRead_Wait_Info[cmd.cmd].flag = DEF_COM_FALSE;

    Com_u8 cnt = 0;
again:
    if(cnt >= 2)
    {
        return;
    }

    InPer_UartSend_Data(&cmd,data);
    InPer_UartRead_Wait_Flag(cmd.cmd);
    if(g_InPer_UartRead_Wait_Info[cmd.cmd].flag == DEF_COM_FALSE)
    {
        PRT_NORMAL("cmd send again: %02x\n",cmd.cmd);
        cnt++;
        goto again;
    }
#endif
    return;
}

Com_void Ext_InPer_UartHandle_Version(Com_pu8 buf)
{
    Com_s32 ver = buf[6];
    Com_s8 mcu_ver_str[4];

    memset(mcu_ver_str,0,sizeof(mcu_ver_str));

    PRT_INFO(DEF_TAG,"mcu ver: %d\n",ver);
    sprintf(mcu_ver_str,"%d",ver);
    Ext_InComFile_Write(DEF_TXT_MCU_VERSION,mcu_ver_str,sizeof(mcu_ver_str));
}

Com_s32 Ext_InPer_UartSend_Ota_Start(Com_void)
{
    FILE *fp = NULL;
    Com_s32 length = 0;
    Com_u8 serial_data[12];

    memset(serial_data,0,sizeof(serial_data));

    if(Ext_InComFile_Access(DEF_BIN_MCU) == DEF_COM_FILE_NOT_EXIST)
    {
        PRT_ERR(DEF_TAG,"not find mcu bin\n");
        Ext_InComFile_JudgeRemove(DEF_FLAG_MCU_NEED_UPGRADE);
        return -1;
    }

    if((fp = fopen(DEF_BIN_MCU,"r+t")) != NULL)
    {
        fseek(fp,0,SEEK_END);
        length = ftell(fp);
        fclose(fp);
    }

    Ext_InPer_Uart_Set_Ota_Total_Len(length);
    PRT_INFO(DEF_TAG,"len: %d\n",length);

    Com_s32 len = 0;
    SUartCmdAndLen cmd;

    cmd.cmd = COMMAND_START_UPGRADE;
    cmd.len = 4;

    serial_data[len++] = length / 0x1000000;
    serial_data[len++] = length / 0x10000;
    serial_data[len++] = length / 0x100;
    serial_data[len++] = length % 0x100;

    g_InPer_UartRead_Wait_Info[COMMAND_START_UPGRADE].flag = DEF_COM_FALSE;
    InPer_UartSend_Data(&cmd,serial_data);

    return 0;
}

Com_s32 Ext_InPer_UartSend_Ota_Package(Com_s32 count)
{
    Com_s32 len = 0;
    Com_s32 length = 0;
    Com_u8 serial_data[DEF_PER_UART_BUF_SIZE];
    FILE *fp;

    memset(serial_data,0,sizeof(serial_data));

    fp = fopen(DEF_BIN_MCU,"r");
    if(fp == NULL)
    {
        PRT_ERR(DEF_TAG,"%s fopen failed\n",__func__);
        return -1;
    }

    fseek(fp,count * 256,SEEK_SET);

    serial_data[length++] = count * 256 / 0x1000000;
    serial_data[length++] = count * 256 / 0x10000;
    serial_data[length++] = count * 256 / 0x100;
    serial_data[length++] = count * 256 % 0x100;

    len = fread(serial_data + length,1,256,fp);
    if(len < 0)
    {
        PRT_ERR(DEF_TAG,"%s end of fread\n",__func__);
        return -1;
    }
    else if (len == 0)
    {
        PRT_WARN(DEF_TAG,"last one package\n");
    }

    fclose(fp);

    SUartCmdAndLen cmd;

    cmd.cmd = COMMAND_TRANSFER_UPGRADE_PACKAGE;
    cmd.len = len + 4;

    g_InPer_UartRead_Wait_Info[cmd.cmd].flag = DEF_COM_FALSE;
    InPer_UartSend_Data(&cmd,serial_data);

    InPer_UartRead_Result(cmd.cmd);

    return 0;
}

Com_s32 send_cmd_mcu_notice_reset(Com_void)
{
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_MCU_NOTICE_RESET;
    cmd.len = 0x01;
    data[0] = 0x01;
    InPer_UartSend_Data(&cmd,data);

    return 0;
}

Com_void Ext_InPer_UartHandle_Reset(Com_void)
{
    static Com_u8 g_InPer_Key_Reset_Flag = DEF_COM_FALSE;

    if(g_InPer_Key_Reset_Flag == DEF_COM_FALSE)
    {
        g_InPer_Key_Reset_Flag = DEF_COM_TRUE;

        send_cmd_mcu_notice_reset();
        Ext_InComFile_Creat(DEF_FLAG_RESTORE_FACTORY);
        Ext_InSdkSpkPlay_WavInit(DEF_WAV_DING_DONG);
        sleep(3);
        PRT_NORMAL("system factory reset !\n");
        Ext_InSdkTcpSystem_Cmd("reboot");
    }
}

Com_void Ext_InPer_UartSend_Record_Mode(Com_u8 mode)
{
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_RECORD_MODE;
    cmd.len = 0x01;

    data[0] = mode;
    InPer_UartSend_Data(&cmd,data);
}

Com_void Ext_InPer_UartSend_Led_Status(Com_s32 val)
{
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_LED_ONOFF;
    cmd.len = 0x01;

    data[0] = val;
    InPer_UartSend_Data(&cmd,data);
}

Com_void Ext_InPer_UartSend_Heartbeat(Com_void)
{
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_HEARTBEAT;
    cmd.len = 0x00;

    InPer_UartSend_Data(&cmd,data);
}

Com_void Ext_InPer_UartSend_Report_Init_Status(Com_void)
{
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_MCU_REPORT_INIT_STATUS;
    cmd.len = 0x00;

    g_InPer_UartRead_Wait_Info[cmd.cmd].flag = DEF_COM_FALSE;
    InPer_UartSend_Data(&cmd,data);
    InPer_UartRead_Result(cmd.cmd);
}

Com_void Ext_InPer_UartSend_Bool_SW(Com_s32 dp_id, Com_s32 val)
{
    SUartCmdAndLen cmd;
    Com_u8 data[4];

    memset(data,0,sizeof(data));

    cmd.cmd = COMMAND_SET_MCU_FUNCTION_SW;
    cmd.len = 0x02;

    data[0] = dp_id;
    data[1] = val;

    InPer_UartSend_Data(&cmd,data);
    InPer_UartRead_Wait_Flag(COMMAND_SET_MCU_FUNCTION_SW);
    if(g_InPer_UartRead_Wait_Info[COMMAND_SET_MCU_FUNCTION_SW].flag == DEF_COM_FALSE)
    {
        printf("cmd send again: %02x\n",COMMAND_SET_MCU_FUNCTION_SW);
    }
    return;
}

Com_void Ext_InPer_UartHandle_Bool_SW(Com_pu8 buf)
{
    // Com_s32 dp_id = buf[6];
    // Com_s32 val = buf[7];
}

